#ifndef PROPAGATION_MODELS_H
#define PROPAGATION_MODELS_H

#include "ns3/object.h"
#include "ns3/propagation-loss-model.h"

namespace ns3 {

/**
 * \ingroup sagin
 * \brief 地面基站传播模型
 */
class GroundStationPropagationLossModel : public PropagationLossModel
{
public:
    /**
     * \brief Get the TypeId
     * \return The TypeId
     */
    static TypeId GetTypeId();
    
    /**
     * Default constructor
     */
    GroundStationPropagationLossModel();
    
    /**
     * \brief Set the coverage radius of the ground station
     * \param radius The radius in meters
     */
    void SetCoverageRadius(double radius);
    
    /**
     * \brief Get the coverage radius of the ground station
     * \return The radius in meters
     */
    double GetCoverageRadius() const;
    
private:
    /**
     * \brief Calculate the rx power based on the tx power and location
     * \param txPowerDbm Transmission power in dBm
     * \param a A mobility model
     * \param b Another mobility model
     * \return The received power in dBm
     */
    virtual double DoCalcRxPower(double txPowerDbm,
                               Ptr<MobilityModel> a,
                               Ptr<MobilityModel> b) const;
    
    /**
     * \brief Copy the random variable stream assignments
     * \param stream The first stream index to use
     * \return The number of streams that have been assigned
     */
    virtual int64_t DoAssignStreams(int64_t stream);
    
    double m_coverageRadius; // 覆盖半径 (米)
};

/**
 * \ingroup sagin
 * \brief 卫星传播模型
 */
class SatellitePropagationLossModel : public PropagationLossModel
{
public:
    /**
     * \brief Get the TypeId
     * \return The TypeId
     */
    static TypeId GetTypeId();
    
    /**
     * Default constructor
     */
    SatellitePropagationLossModel();
    
    /**
     * \brief Set the maximum elevation angle
     * \param angle The angle in degrees
     */
    void SetMaximumElevationAngle(double angle);
    
    /**
     * \brief Get the maximum elevation angle
     * \return The angle in degrees
     */
    double GetMaximumElevationAngle() const;
    
private:
    /**
     * \brief Calculate the rx power based on the tx power and location
     * \param txPowerDbm Transmission power in dBm
     * \param a A mobility model
     * \param b Another mobility model
     * \return The received power in dBm
     */
    virtual double DoCalcRxPower(double txPowerDbm,
                               Ptr<MobilityModel> a,
                               Ptr<MobilityModel> b) const;
    
    /**
     * \brief Copy the random variable stream assignments
     * \param stream The first stream index to use
     * \return The number of streams that have been assigned
     */
    virtual int64_t DoAssignStreams(int64_t stream);
    
    double m_maximumElevationAngle; // 最大仰角 (度)
};

/**
 * \ingroup sagin
 * \brief 传播模型工厂
 */
class PropagationModelFactory
{
public:
    /**
     * \brief Create a ground station propagation model
     * \param coverageRadius The coverage radius in meters
     * \return A pointer to the propagation model
     */
    static Ptr<PropagationLossModel> CreateGroundStationPropagationModel(double coverageRadius);
    
    /**
     * \brief Create a satellite propagation model
     * \param maximumElevationAngle The maximum elevation angle in degrees
     * \return A pointer to the propagation model
     */
    static Ptr<PropagationLossModel> CreateSatellitePropagationModel(double maximumElevationAngle);
};

} // namespace ns3

#endif /* PROPAGATION_MODELS_H */
